package org.example.calculator;

import org.example.entity.CustomerOrder;
import org.example.entity.CustomerRepayPlan;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Vintage和迁徙率计算器
 */
public class VintageCalculator {
    
    /**
     * 计算迁徙率
     * M1-M2迁徙率 = M1中逾期有X万，其中有Y万一直不还，拖欠到M2，则M1-M2的迁徙率=Y/X
     */
    public static Map<String, BigDecimal> calculateMigrationRate(List<CustomerRepayPlan> allPlans) {
        Map<String, BigDecimal> migrationRates = new HashMap<>();
        
        // 按订单号分组
        Map<String, List<CustomerRepayPlan>> plansByOrder = allPlans.stream()
                .collect(Collectors.groupingBy(CustomerRepayPlan::getOrderNo));
        
        int m1Count = 0; // M1逾期数量
        int m1ToM2Count = 0; // M1到M2的迁徙数量
        
        for (Map.Entry<String, List<CustomerRepayPlan>> entry : plansByOrder.entrySet()) {
            List<CustomerRepayPlan> orderPlans = entry.getValue();
            
            // 检查是否有M1逾期
            boolean hasM1Overdue = orderPlans.stream()
                    .anyMatch(plan -> "逾期未还".equals(plan.getRepayStatus()) && 
                            plan.getOverdueDays() != null && plan.getOverdueDays() > 0 && plan.getOverdueDays() <= 30);
            
            if (hasM1Overdue) {
                m1Count++;
                
                // 检查是否继续逾期到M2
                boolean hasM2Overdue = orderPlans.stream()
                        .anyMatch(plan -> "逾期未还".equals(plan.getRepayStatus()) && 
                                plan.getOverdueDays() != null && plan.getOverdueDays() > 30 && plan.getOverdueDays() <= 60);
                
                if (hasM2Overdue) {
                    m1ToM2Count++;
                }
            }
        }
        
        if (m1Count > 0) {
            BigDecimal migrationRate = BigDecimal.valueOf(m1ToM2Count)
                    .divide(BigDecimal.valueOf(m1Count), 4, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(100));
            migrationRates.put("M1-M2迁徙率", migrationRate);
        }
        
        return migrationRates;
    }
    
    /**
     * 计算Vintage逾期率
     * 某个时点的累计逾期率（X+） = （在该时点逾期天数 > X 的贷款本金余额 / 该Vintage的初始发放贷款总额） * 100%
     */
    public static Map<String, Map<String, BigDecimal>> calculateVintageRates(List<CustomerOrder> orders, 
                                                                           List<CustomerRepayPlan> allPlans) {
        Map<String, Map<String, BigDecimal>> vintageResults = new HashMap<>();
        
        // 按放款月份分组Vintage
        Map<String, List<CustomerOrder>> vintagePools = orders.stream()
                .collect(Collectors.groupingBy(order -> {
                    String frTime = order.getFrTime();
                    return frTime.substring(0, 7); // 取年月部分
                }));
        
        for (Map.Entry<String, List<CustomerOrder>> vintageEntry : vintagePools.entrySet()) {
            String vintageMonth = vintageEntry.getKey();
            List<CustomerOrder> vintageOrders = vintageEntry.getValue();
            
            // 计算该Vintage的初始发放总额
            BigDecimal initialAmount = vintageOrders.stream()
                    .map(CustomerOrder::getLoanAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            
            Map<String, BigDecimal> vintageRates = new HashMap<>();
            
            // 计算不同逾期天数的逾期率
            int[] overdueDays = {0, 30, 60, 90};
            String[] rateNames = {"Vintage0+", "Vintage30+", "Vintage60+", "Vintage90+"};
            
            for (int i = 0; i < overdueDays.length; i++) {
                int minOverdueDays = overdueDays[i];
                String rateName = rateNames[i];
                
                // 计算逾期本金余额
                BigDecimal overdueAmount = calculateOverdueAmount(vintageOrders, allPlans, minOverdueDays);
                
                // 计算逾期率
                if (initialAmount.compareTo(BigDecimal.ZERO) > 0) {
                    BigDecimal rate = overdueAmount
                            .divide(initialAmount, 4, RoundingMode.HALF_UP)
                            .multiply(BigDecimal.valueOf(100));
                    vintageRates.put(rateName, rate);
                } else {
                    vintageRates.put(rateName, BigDecimal.ZERO);
                }
            }
            
            vintageResults.put(vintageMonth, vintageRates);
        }
        
        return vintageResults;
    }
    
    /**
     * 计算逾期本金余额
     */
    private static BigDecimal calculateOverdueAmount(List<CustomerOrder> vintageOrders, 
                                                   List<CustomerRepayPlan> allPlans, 
                                                   int minOverdueDays) {
        Set<String> vintageOrderNos = vintageOrders.stream()
                .map(CustomerOrder::getOrderNo)
                .collect(Collectors.toSet());
        
        return allPlans.stream()
                .filter(plan -> vintageOrderNos.contains(plan.getOrderNo()))
                .filter(plan -> "逾期未还".equals(plan.getRepayStatus()))
                .filter(plan -> plan.getOverdueDays() != null && plan.getOverdueDays() > minOverdueDays)
                .map(plan -> {
                    // 计算剩余本金（简化计算）
                    BigDecimal remainingPrincipal = plan.getLoanAmount()
                            .subtract(plan.getNowPayPrincipal() != null ? plan.getNowPayPrincipal() : BigDecimal.ZERO);
                    return remainingPrincipal.max(BigDecimal.ZERO);
                })
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
    
    /**
     * 生成Vintage报告
     */
    public static void generateVintageReport(Map<String, Map<String, BigDecimal>> vintageResults) {
        System.out.println("\n=== Vintage逾期率报告 ===");
        System.out.printf("%-12s %-12s %-12s %-12s %-12s%n", 
                "Vintage月份", "Vintage0+", "Vintage30+", "Vintage60+", "Vintage90+");
        System.out.println("------------------------------------------------------------");
        
        for (Map.Entry<String, Map<String, BigDecimal>> entry : vintageResults.entrySet()) {
            String vintageMonth = entry.getKey();
            Map<String, BigDecimal> rates = entry.getValue();
            
            System.out.printf("%-12s %-12.2f %-12.2f %-12.2f %-12.2f%n",
                    vintageMonth,
                    rates.getOrDefault("Vintage0+", BigDecimal.ZERO).doubleValue(),
                    rates.getOrDefault("Vintage30+", BigDecimal.ZERO).doubleValue(),
                    rates.getOrDefault("Vintage60+", BigDecimal.ZERO).doubleValue(),
                    rates.getOrDefault("Vintage90+", BigDecimal.ZERO).doubleValue());
        }
    }
    
    /**
     * 生成迁徙率报告
     */
    public static void generateMigrationReport(Map<String, BigDecimal> migrationRates) {
        System.out.println("\n=== 迁徙率报告 ===");
        for (Map.Entry<String, BigDecimal> entry : migrationRates.entrySet()) {
            System.out.printf("%s: %.2f%%%n", entry.getKey(), entry.getValue().doubleValue());
        }
    }
}
